import warnings
warnings.warn("qturboframe.public_ui.ucf_h_ui.table模块已被废弃，替代模块为qturboframe.public_ui.h_ui.table", DeprecationWarning)

import re
import copy

from qturboframe.lib.report.log import logger
from qturboframe.lib.ranorex.exceptions import CsClientError
from qturboframe.lib.ranorex.web_element.web_element import WebElement
from qturboframe.lib.ranorex.web_element.div_tag import DivTag
from qturboframe.lib.ranorex.web_element.th_tag import ThTag
from qturboframe.lib.ranorex.web_element.td_tag import TdTag
from qturboframe.lib.ranorex.web_element.span_tag import SpanTag
from ..ucf_base_element import BaseElement
from .page import Page
from .base_table import BaseTable


class Table(BaseElement):
    '''
    hui的表格操作

    :Attributes:
     - _page: 当前表格的分页栏对象
     - _fixed_div: 当前表格中固定栏元素
    '''

    _page = Page
    _fixed_div = WebElement

    def __init__(self, element_para, father=None, timeout=10000):
        super().__init__(element_para, father, timeout)
        self._element = DivTag(self._element.control)
        self.page()
        self.fixed()

    def page(self, idname=None, father=None):
        '''
        获取hui表格分页栏对象

        :Args:
         - idname: 分页栏的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 分页栏的祖先级元素，可以给分页栏查找限定范围，默认为表格元素

        :Returns:
            返回分页栏对象

        :Example:
         - 例: table.page({'xpath':'./following-sibling::ul[@class="h-page"]'})
        '''
        if father is None:
            father = self.element
        if idname:
            self._page = Page(idname, father, 100)
        else:
            self._page = Page(
                {'xpath':'./following-sibling::ul[@class~\'h-page\']'}, father, 100)
        return self._page

    def fixed(self, idname=None, father=None):
        '''
        获取表格固定栏

        :Args:
         - idname: 固定栏的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 固定栏的祖先级元素，可以给固定栏查找限定范围，默认为表格元素

        :Returns:
            返回固定栏对象，固定栏不存在则返回None

        :Example:
         - 例: table.fixed({'xpath':'./div/div[@class="h-table-fixed"]'})
        '''
        if father is None:
            father = self.element
        if idname:
            try:
                self._fixed_div = BaseElement(idname, father, timeout=100).element
            except CsClientError:
                self._fixed_div = None
        else:
            self._fixed_div = father.exist('xpath', './div/div[@class=\'h-table-fixed\' or '
                                                    '@class=\'h-table-fixed-right\']', timeout=100)
        if self._fixed_div:
            self._fixed_div = DivTag(self._fixed_div.control)
        return self._fixed_div

    def export(self, file_name):
        '''
        获取hui表格当前页的内容，并导出到xls文件，目前不支持xlsx

        :Args:
         - file_name:导出的文件名，含路径

        :Raises:
            SeleniumError: 获取表格数据出错或者导出表格出错

        :Example:
         - 例: table.export('D:/a.xls')
        '''
        fixed_title_list = list()
        fixed_text_list = list()
        if self._fixed_div:
            # 获取冻结列列名和内容
            fixed_head_table = BaseTable(
                {'xpath':'./div[@class~\'h-table-fixed-header\']/table'}, self._fixed_div, self.timeout)
            fixed_body_table = BaseTable(
                {'xpath':'./div[@class~\'h-table-fixed-body\']/table'}, self._fixed_div, self.timeout)
            fixed_title_list = fixed_head_table.get_title_list()
            logger.info('表格冻结列显示列名：' + str(fixed_title_list))
            fixed_text_list = fixed_body_table.get_text_list()
        # 获取非冻结列列名和内容
        head_table = BaseTable(
            {'xpath':'./div/div[@class=\'h-table-header\']/table'}, self.element, self.timeout)
        title_list = head_table.get_title_list()
        logger.debug('表格显示列名：' + str(title_list))
        body_table = BaseTable(
            {'xpath':'./div/div[@class=\'h-table-body\']/table'}, self.element, self.timeout)
        text_list = body_table.get_text_list()
        # 合并表格
        title_list, text_list = self.__join_list(fixed_title_list, title_list,
                                                 fixed_text_list, text_list)
        rows = int(len(text_list)/len(title_list))
        cols = len(title_list)
        title_list.extend(text_list)
        # 导出表格内容到Excel
        from qturboframe.lib.utils.excel import ExcelWrite
        excel = ExcelWrite()
        excel.write_by_table_data('sheet0', title_list, rows + 1, cols)
        excel.save(file_name)

    def get_cell_by_row_index(self, title_name, row):
        '''
        根据列名和行数查找hui表格的单元格

        :Args:
         - title_name: 列名
         - row: 单元格所在的行数

        :Returns:
            返回查找的单元格

        :Example:
         - 例: table.get_cell_by_row_index('name', 2)
        '''
        if row == 0:
            raise CsClientError('表格中没有第0行！')
        logger.debug('开始表格单元格查询')
        # 查看是否存在冻结列
        fixed_title_list = list()
        if self._fixed_div:
            # 获取冻结列列名列表
            fixed_head_table = BaseTable(
                {'xpath': './div[@class~\'h-table-fixed-header\']/table'}, self._fixed_div, self.timeout)
            fixed_title_list = fixed_head_table.get_title_list()
            logger.debug('表格冻结列显示列名：' + str(fixed_title_list))
        # 获取列名列表
        head_table = BaseTable(
            {'xpath': './div/div[@class=\'h-table-header\']/table'}, self.element, self.timeout)
        title_list = head_table.get_title_list()
        logger.debug('表格显示列名：' + str(title_list))
        # 进行翻页判断，需要翻页则翻页
        if self._page.exist():
            # 获取表格每页显示行数
            rows = self._page.get_rows_in_page()
            if rows == 0:
                # 获取初始数据表格
                bodytable = BaseTable(
                    {'xpath': './div/div[@class=\'h-table-body\']/table'}, self.element, self.timeout)
                tr_list = bodytable.get_tr_list()
                rows = len(tr_list)
            # 行数若超过当前页面显示行数，则翻页
            if row <= 0:
                raise CsClientError('表格行号出错！')
            else:
                if row % rows == 0:
                    pages = int(row / rows)
                    row = rows
                else:
                    pages = int(row / rows + 1)
                    row = row % rows
                self._page.to_page(pages)
                logger.debug('跳转到表格第' + str(pages) + '页。')
        # 根据列名和行数查找单元格
        table_cell = self.__get_cell(fixed_title_list, title_list, title_name, row)
        logger.debug('单元格查询结束！')
        return table_cell

    def get_cell(self, table_dict:dict, title_name, turn_page=False):
        '''
        根据单元格列名和单元格内容查找hui表格中所在的单元格

        :Args:
         - table_dict: 列名和内容，字典类型，例：{列名1:内容1,列名2:内容2}
         - title_name: 查找的单元格列名
         - turn_page: 是否自动翻页，默认关闭自动翻页查找功能

        :Returns:
            返回查找的单元格

        :Example:
         - 例: cell = table.get_cell({'姓名':'admin', '年龄':'25'}, '工号', True)
        '''
        # 表格数据检查
        key_list = list(table_dict.keys())
        for key in key_list:
            if table_dict.get(key) == '-':
                table_dict.pop(key)
        if not table_dict:
            logger.info('表格查询条件为空！')
            return None
        logger.info('开始表格行号查询')
        # 将表格翻至首页，然后进行逐页查找
        if self._page.exist():
            self._page.to_first()
        # 查看是否存在冻结列
        fixed_title_list = list()
        if self._fixed_div:
            # 获取冻结列列名列表
            fixed_head_table = BaseTable(
                {'xpath': './div[@class~\'h-table-fixed-header\']/table'}, self._fixed_div, self.timeout)
            fixed_title_list = fixed_head_table.get_title_list()
            logger.debug('表格冻结列显示列名：' + str(fixed_title_list))
        # 获取列名列表
        head_table = BaseTable(
            {'xpath': './div/div[@class=\'h-table-header\']/table'}, self._element, self.timeout)
        title_list = head_table.get_title_list()
        logger.debug('表格显示列名：' + str(title_list))
        row = self._get_row_index(fixed_title_list, title_list, table_dict, turn_page)
        logger.debug('表格行号查询结束！')
        if row == 0:
            raise CsClientError('未根据查找条件找到表格行！')
        logger.debug('开始表格单元格查询')
        table_cell = self.__get_cell(fixed_title_list, title_list, title_name, row)
        logger.debug('单元格查询结束！')
        return table_cell

    def select_rows(self, table_dict, turn_page=False):
        '''
        在当前页根据单元格列名和单元格内容勾选行

        :Args:
         - table_dict: 单元格列名和单元格内容，字典类型，例：{列名1:内容1,列名2:内容2}
         - turn_page: 是否自动翻页，默认关闭自动翻页查找功能

        :Example:
         - 例: table.select_rows({'姓名':'admin, manager'})
        '''
        re_checked = 'h-checkbox-checked'
        # 表格数据检查
        key_list = list(table_dict.keys())
        for key in key_list:
            if table_dict.get(key) == '-':
                table_dict.pop(key)
        if not table_dict:
            logger.debug('表格查询条件为空，不勾选！')
            return
        elif table_dict.get('_all_'):
            logger.info('当前表格页全选！')
            self.select_all()
        else:
            logger.info('开始表格行号查询')
            # 将表格翻至首页，然后进行逐页查找
            if self._page.exist():
                self._page.to_first()
            # 查看是否存在冻结列
            fixed_title_list = list()
            if self._fixed_div:
                # 获取冻结列列名列表
                fixed_head_table = BaseTable(
                    {'xpath': './div[@class~\'h-table-fixed-header\']/table'}, self._fixed_div, self.timeout)
                fixed_title_list = fixed_head_table.get_title_list()
                logger.debug('表格冻结列显示列名：' + str(fixed_title_list))
            # 获取列名列表
            head_table = BaseTable(
                {'xpath': './div/div[@class=\'h-table-header\']/table'}, self._element, self.timeout)
            title_list = head_table.get_title_list()
            logger.debug('表格显示列名：' + str(title_list))
            row_list = self.__get_row_indexes(fixed_title_list, title_list, table_dict, turn_page)
            logger.debug('表格行号查询结束！')
            if len(row_list) == 0:
                raise CsClientError('未找到目标数据行！')
            logger.debug('开始勾选表格行！')
            body_table = BaseTable(
                {'xpath': './div/div[@class=\'h-table-body\']/table'}, self._element, self.timeout)
            tr_list = body_table.get_tr_list()
            for row in row_list:
                td = TdTag(tr_list[int(row - 1)].find_elements_by_attribute(
                    'xpath', './/td', timeout=self.timeout)[0].control)
                span = SpanTag(td.find_element_by_attribute(
                    'xpath', './/label[@class~\'h-checkbox-wrapper\']/span[@class~\'h-checkbox\']',
                    timeout=self.timeout).control)
                if not re.search(re_checked, span.get_attribute('class')):
                    span.secure_click()
            logger.debug('勾选表格行结束！')

    def select_row(self, table_dict, turn_page=False):
        '''
        在当前页根据单元格列名和单元格内容勾选行

        :Args:
         - table_dict: 单元格列名和单元格内容，字典类型，例：{列名1:内容1,列名2:内容2}
         - turn_page: 是否自动翻页，默认关闭自动翻页查找功能

        :Example:
         - 例: table.select_row({'姓名':'admin','年龄':'25'}, True)
        '''
        re_checked = 'h-checkbox-checked'
        # 表格数据检查
        key_list = list(table_dict.keys())
        for key in key_list:
            if table_dict.get(key) == '-':
                table_dict.pop(key)
        if not table_dict:
            logger.info('表格查询条件为空！')
            return
        logger.info('开始表格行号查询')
        # 将表格翻至首页，然后进行逐页查找
        if self._page.exist():
            self._page.to_first()
        # 查看是否存在冻结列
        fixed_title_list = list()
        if self._fixed_div:
            # 获取冻结列列名列表
            fixed_head_table = BaseTable(
                {'xpath': './div[@class~\'h-table-fixed-header\']/table'}, self._fixed_div, self.timeout)
            fixed_title_list = fixed_head_table.get_title_list()
            logger.debug('表格冻结列显示列名：' + str(fixed_title_list))
        # 获取列名列表
        head_table = BaseTable(
            {'xpath': './div/div[@class=\'h-table-header\']/table'}, self._element, self.timeout)
        title_list = head_table.get_title_list()
        logger.debug('表格显示列名：' + str(title_list))
        row = self._get_row_index(fixed_title_list, title_list, table_dict, turn_page)
        logger.debug('表格行号查询结束！')
        if row == 0:
            raise CsClientError('未找到目标数据行！')
        logger.debug('开始勾选表格行！')
        body_table = BaseTable(
            {'xpath': './div/div[@class=\'h-table-body\']/table'}, self._element, self.timeout)
        tr_list = body_table.get_tr_list()
        td = TdTag(tr_list[int(row - 1)].find_elements_by_attribute(
            'xpath', './/td', timeout=self.timeout)[0].control)
        span = SpanTag(td.find_element_by_attribute(
            'xpath', './/label[@class~\'h-checkbox-wrapper\']/span[@class~\'h-checkbox\']',
            timeout=self.timeout).control)
        if not re.search(re_checked, span.get_attribute('class')):
            span.secure_click()
        logger.debug('勾选表格行结束！')

    def select_all(self):
        '''
        当前页表格行全选

        :Example:
         - 例: table.select_all()
        '''
        re_checked = 'h-checkbox-checked'
        th = ThTag(self._element.find_elements_by_attribute(
            'xpath', './div/div[@class=\'h-table-header\']/table/thead/tr/th',
            timeout=self.timeout)[0].control)
        span = SpanTag(th.find_element_by_attribute(
                'xpath', './/label[@class~\'h-checkbox-wrapper\']/span[@class~\'h-checkbox\']',
            timeout=self.timeout).control)
        if not re.search(re_checked, span.get_attribute('class')):
            span.secure_click()

    def check_cells_exist(self, table_dict, turn_page=False):
        '''
        检查单元格是否存在

        :Args:
         - table_dict: 一组单元格列名和单元格内容，字典类型，例：{列名1:'内容1,内容2'}
         - turn_page: 是否自动翻页，默认关闭自动翻页查找功能

        :Example:
         - 例: table.check_cells_exist({'姓名':'admin, manager'}, True)
        '''
        # 表格数据检查
        key_list = list(table_dict.keys())
        for key in key_list:
            if table_dict.get(key) == '-':
                table_dict.pop(key)
        if not table_dict:
            raise AttributeError('表格检查条件为空！')
        if turn_page:
            if self._page.exist():
                self._page.to_first()
        # 查看是否存在冻结列
        fixed_title_list = list()
        if self._fixed_div:
            # 获取冻结列列名列表
            fixed_head_table = BaseTable(
                {'xpath': './/div[@class~\'h-table-fixed-header\']/table'}, self._fixed_div, self.timeout)
            fixed_title_list = fixed_head_table.get_title_list()
            logger.debug('表格冻结列显示列名：' + str(fixed_title_list))
        # 获取列名列表
        head_table = BaseTable(
            {'xpath': './div/div[@class=\'h-table-header\']/table'}, self._element, self.timeout)
        title_list = head_table.get_title_list()
        logger.debug('表格显示列名：' + str(title_list))
        # 查找单元格
        search_value_list = table_dict.get(list(table_dict.keys())[0]).split(',')
        for value in search_value_list:
            search_dict = {list(table_dict.keys())[0]:value}
            row = self._get_row_index(fixed_title_list, title_list, search_dict, turn_page)
            if row:
                logger.info('列名为{}，内容为{}的单元格存在，检查通过！'.format(
                    list(table_dict.keys())[0], value))
            else:
                raise CsClientError('列名为{}，内容为{}的单元格不存在，检查不通过！'.format(
                    list(table_dict.keys())[0], value))

    def _get_row_index(self, fixed_title_list, title_list, table_dict, turn_page=False):
        re_disabled = r'h-page-disabled'
        key_list = list(table_dict.keys())
        logger.debug('表格查找列名索引：' + str(key_list))
        # 以输入数据作为索引查找表格行数
        rows = 0
        row_list = list()
        for i, key in enumerate(key_list):
            temp_list = list()
            text_list = list()
            # 查看是否存在冻结列
            if fixed_title_list:
                # 获取冻结列内容列表
                fixed_body_table = BaseTable(
                    {'xpath': './div[@class~\'h-table-fixed-body\']/table'}, self._fixed_div, self.timeout)
                try:
                    title_index = fixed_title_list.index(key)
                    logger.debug('第' + str(title_index + 1) + '列，名称：' + key)
                except:
                    pass
                else:
                    text_list = fixed_body_table.get_text_list(len(fixed_title_list), int(title_index + 1))
            # 获取指定列内容列表
            body_table = BaseTable(
                {'xpath': './div/div[@class=\'h-table-body\']/table'}, self._element, self.timeout)
            if len(text_list) == 0:
                try:
                    title_index = title_list.index(key)
                    logger.debug('第' + str(title_index + len(fixed_title_list) + 1) + '列，名称：' + key)
                except:
                    logger.debug('表格中没有列名：' + key)
                    continue
                else:
                    text_list = body_table.get_text_list(len(title_list), int(title_index + 1))
            if i == 0:
                rows = len(text_list)
                logger.debug('当前页显示行数：' + str(rows))
                row_list = list(range(1, rows + 1))
            for j in row_list:
                if text_list[j - 1] == table_dict[key]:
                    logger.debug('要查找的内容：' + table_dict[key])
                    logger.debug('第' + str(j) + '行，内容：' + text_list[j - 1])
                    temp_list.append(j)
            row_list = temp_list
            if len(row_list) == 0:
                break
        # 未找到数据行则进行表格翻页
        if len(row_list) > 0:
            return row_list[0]
        else:
            if turn_page:
                if self._page.exist():
                    if self._page.is_last():
                        return 0
                    else:
                        self._page.to_next()
                        logger.debug("翻下一页查找。")
                        return self._get_row_index(fixed_title_list, title_list, table_dict, turn_page)
                else:
                    return 0
            else:
                return 0

    def __get_row_indexes(self, fixed_title_list, title_list, table_dict, turn_page=False):
        key_list = list(table_dict.keys())
        logger.debug('表格查找列名索引：' + str(key_list))
        # 以输入数据作为索引查找表格行数
        row_list = list()
        rows = 0
        for i, key in enumerate(key_list):
            text_list = list()
            temp_list = list()
            # 查看是否存在冻结列
            if fixed_title_list:
                # 获取冻结列内容列表
                fixed_body_table = BaseTable(
                    {'xpath': './div[@class~\'h-table-fixed-body\']/table'}, self._fixed_div, self.timeout)
                try:
                    title_index = fixed_title_list.index(key)
                    logger.debug('第' + str(title_index + 1) + '列，名称：' + key)
                except:
                    pass
                else:
                    text_list = fixed_body_table.get_text_list(len(fixed_title_list), int(title_index + 1))
            # 获取指定列内容列表
            if len(text_list) == 0:
                try:
                    title_index = title_list.index(key)
                    logger.debug('第' + str(title_index + 1) + '列，名称：' + key)
                except:
                    logger.debug('表格中没有列名：' + key)
                else:
                    body_table = BaseTable(
                        {'xpath': './div/div[@class=\'h-table-body\']/table'}, self._element, self.timeout)
                    text_list = body_table.get_text_list(len(title_list), int(title_index + 1))
            if i == 0:
                rows = len(text_list)
                logger.debug('当前页显示行数：' + str(rows))
                row_list = list(range(1, rows + 1))
            content_list = table_dict[key].split(',')
            for j in row_list:
                for k in content_list:
                    if text_list[j - 1] == k:
                        logger.debug('要查找的内容：' + k)
                        logger.debug('第' + str(j) + '行，内容：' + text_list[j - 1])
                        temp_list.append(j)
            row_list = temp_list
            if len(row_list) == 0:
                break
        # 判断是否找到数据行
        if len(row_list) > 0:
            return row_list
        else:
            # 翻页查找
            if turn_page:
                if self._page.exist():
                    if not self._page.is_last():
                        self._page.to_next()
                        logger.debug("翻下一页查找。")
                        row_list.extend(self.__get_row_indexes(
                            fixed_title_list, title_list, table_dict, turn_page))
                    else:
                        return row_list
                else:
                    return []
            else:
                return []

    def __get_cell(self, fixed_title_list, title_list, title_name, row):
        table_cell = None
        fixed_cell_list = list()
        # 查看是否存在冻结列
        if fixed_title_list:
            fixed_body_table = BaseTable(
                {'xpath': './div[@class~\'h-table-fixed-body\']/table'}, self._fixed_div, self.timeout)
            fixed_cell_list = fixed_body_table.get_cell_list()
        # 获取数据表格单元格列表
        body_table = BaseTable(
            {'xpath': './div/div[@class=\'h-table-body\']/table'}, self._element, self.timeout)
        cell_list = body_table.get_cell_list()
        # 组合冻结列与非冻结列
        temp_title_list, temp_cell_list = self.__join_list(
            fixed_title_list, title_list, fixed_cell_list, cell_list)
        # 当前表格显示的行数
        rows = len(cell_list) / len(title_list)
        logger.debug(
            '当前页显示行数：{}/{}={}'.format(len(temp_cell_list), len(temp_title_list), rows))
        try:
            title_index = temp_title_list.index(title_name)
            logger.debug('第' + str(title_index + 1) + '列，名称：' + title_name)
        except ValueError:
            raise CsClientError('列名不存在！')
        else:
            cell_index = int(title_index + (len(temp_title_list) * (row - 1)))
            table_cell = temp_cell_list[cell_index]
        return table_cell

    def __join_list(self, tlist1, tlist2, list1, list2):
        templist2 = list()
        for i in range(0, int((len(list1) + len(list2)) / (len(tlist1) + len(tlist2)))):
            for j in range(0, len(tlist1)):
                templist2.append(list1[int(i * len(tlist1) + j)])
            for j in range(0, len(tlist2)):
                templist2.append(list2[int(i * len(tlist2) + j)])
        templist1 = copy.deepcopy(tlist1)
        templist1.extend(tlist2)
        return templist1,templist2
